package com.ltu.ai.sparkdesk.websocket.ultra;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.Handshakedata;
import org.java_websocket.handshake.ServerHandshake;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonRawValue;
import com.google.gson.Gson;
import com.ltu.ai.sparkdesk.websocket.AiContextManager;
import com.ltu.ai.sparkdesk.websocket.iat.IatSocketClient;
import com.ltu.ai.sparkdesk.websocket.ultra.ResponSparkData.RoleContent;
import com.ltu.domain.mp_entity.customize.SessionRecordEntity;
import com.ltu.enums.SysDict;

import lombok.extern.slf4j.Slf4j;



@Slf4j
public class SparkSocketClient extends WebSocketClient {
	
    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS");
 	private static final String TTS_HOST = "tts-api.xfyun.cn/v2/tts";
 	private static final String HostUrl = "https://";
    private  AiContextManager.IatContext iatContext;
    private  AiContextManager aiContextManager;
    // 开始时间
    private  Date dateBegin = new Date();
    // 结束时间
    private  Date dateEnd = null;
    private String  respContext = "";
    
    
    public SparkSocketClient(URI serverUri,AiContextManager aiContextManager,AiContextManager.IatContext iatContext) {
    	  super(serverUri);
    	  
    	  this.iatContext = iatContext;
    	  this.aiContextManager = aiContextManager;
        if(serverUri.toString().contains("wss")){
            trustAllHosts(this);
        }
    }
    
    public static String getCurrentTimeStr() {
        return sdf.format(new Date());
    }
    
    @Override
    public void onOpen(ServerHandshake handshake) {
        System.out.println(getCurrentTimeStr() + "\t Spark大模型Websocket连接建立成功！");
        sendQuestion();
    }
    
    public void sendQuestion() {
        try {
            JSONObject requestJson=new JSONObject();
            JSONObject header=new JSONObject();  // header参数
            header.put("app_id",AiContextManager.APPID);
//            header.put("uid",UUID.randomUUID().toString().substring(0, 10));

            JSONObject parameter=new JSONObject(); // parameter参数
            JSONObject chat=new JSONObject();
            //domain参数查看https://www.xfyun.cn/doc/spark/Web.html#_1-%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E
            chat.put("domain","4.0Ultra"); //
            chat.put("temperature", 0.2);
            chat.put("max_tokens", 5105);
            parameter.put("chat",chat);

            JSONObject payload=new JSONObject(); // payload参数
            JSONObject message=new JSONObject();
            JSONArray params = (JSONArray) JSONArray.toJSON(iatContext.getHistoryList());
            JSONArray arr = new JSONArray();
            RoleContent  rc = new RoleContent(SysDict.SessionRole.SystemAI.getName(),"资深高级律师,请根据我的提问，给出专业的，包含权利、责任和义务的法律建议，引用相关法律条文作为建议依据，并做出风险提示和应对解决办法",null);
            arr.add(JSONObject.toJSON(rc));
            arr.addAll(params);
            message.put("text",arr);
            payload.put("message",message);
            requestJson.put("header",header);
            requestJson.put("parameter",parameter);
            requestJson.put("payload",payload);
            String body = requestJson.toString();
              log.info("\n\t" + body); // 可以打印看每次的传参明细
            this.send(body);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
     
//  @Override
//  public void onMessage(ByteBuffer bytes) {
//      try {
//          System.out.println(getCurrentTimeStr() + "\t服务端返回：" + new String(bytes.array(), "UTF-8"));
//      } catch (UnsupportedEncodingException e) {
//          e.printStackTrace();
//      }
//  }

    @Override
    public void onMessage(String text) {
    	log.info("AI响应结果：{}",text);
    	Gson  gson = new Gson();
    	ResponSparkData resp = gson.fromJson(text, ResponSparkData.class);
    	if(resp.getHeader().getCode()!=0) {
    		log.error("AI响应出错：{}",text);
    		return;
    	}
    	//再将相应的数据发送给客户端
    	if( resp.getPayload().getChoices().getText()==null)
    		return;
    	
    	 String respMsg = resp.getPayload().getChoices().getText().stream().map( a -> a.getContent())
    			 .collect( Collectors.joining(""));
    	 
         RoleContent  rc = new RoleContent(SysDict.SessionRole.ChatAI.getName(),respMsg,"");
         iatContext.getHistoryList().add(rc);
         iatContext.checkContextMax();
    	 this.respContext =  this.respContext+respMsg;
    	//如果 ResponSparkData.header.status == 2 说明相应结束了数据存到数据，且加入历史
    	   if (resp.getHeader().getStatus() == 2) {
               dateEnd = new Date();
              log.info(sdf.format(dateBegin) + "开始");
              log.info(sdf.format(dateEnd) + "结束");
              log.info("耗时:" + (dateEnd.getTime() - dateBegin.getTime()) + "ms");
              log.info("最终完整答案 ==》" + respContext);
              log.info("本次识别sid ==》" + resp.getHeader().getSid());
              log.info("本次消耗token ==》" + resp.getPayload().getUsage().getJSONObject("text").toJSONString());
       
              Integer totalToken = (resp.getPayload().getUsage().getJSONObject("text").getInteger("total_tokens"));
              SessionRecordEntity record = new SessionRecordEntity();
          	record.setDeviceMac(iatContext.getDeviceMac() )
          		  .setContent(respContext)
          		  .setRole(SysDict.SessionRole.ChatAI.getName())
          		  .setCreateTime(new Date())
          		  .setSessionId(Integer.parseInt(iatContext.getSessionEntity().getId()))
          		  .setTotalToken(totalToken);
          	
          	iatContext.getSessionEntity().setTotalQuestion( iatContext.getSessionEntity().getTotalQuestion()+1);
          	iatContext.getSessionEntity().setTotalToken(iatContext.getSessionEntity().getTotalToken() +  totalToken);
          	
        	try {
        		JSONObject  jsonRC = new JSONObject();
               String	authUrl = AiContextManager.getAuthUrl(HostUrl + TTS_HOST).replace("http://", "ws://").replace("https://", "wss://");
               jsonRC.put("authUrl",authUrl);
               jsonRC.put("content", rc.getContent());
               jsonRC.put("role", rc.getRole());
               log.info("输送设备号：{},结果：{}",iatContext.getDeviceMac(),jsonRC.toString());
               if(iatContext.getSessionEntity().getTotalQuestion() == 1) { 
            	    String wxQrCode = aiContextManager.getCurSessionQRCode(iatContext.getSessionEntity());
            	    jsonRC.put("wxQrCode", wxQrCode);
               }               
               aiContextManager.responClient( iatContext.getDeviceMac(),jsonRC);
               aiContextManager.saveSessionRecord(record,iatContext.getSessionEntity());
              this.close(1000, "Spark 4.0Ultra 回答完毕");
              this.respContext ="";
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
            
           } else {
               // todo 根据返回的数据处理
        	   log.info("输送设备号：{},结果：{}",iatContext.getDeviceMac(),JSONObject.toJSONString(rc));
        	   aiContextManager.responClient( iatContext.getDeviceMac(),rc);
			}
    		
    }

    @Override
    public void onError(Exception e) {
        System.out.println(getCurrentTimeStr() + "\t连接发生错误：" + e.getMessage() + ", " + new Date());
        e.printStackTrace();
    }

    @Override
    public void onClose(int arg0, String arg1, boolean arg2) {
        System.out.println(getCurrentTimeStr() + "\t Spark-ultra 链接关闭");
    }


    public void trustAllHosts(SparkSocketClient appClient) {
        System.out.println("wss");
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }

            @Override
            public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                // TODO Auto-generated method stub

            }

            @Override
            public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                // TODO Auto-generated method stub

            }
        }};

        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, trustAllCerts, new java.security.SecureRandom());
            appClient.setSocket(sc.getSocketFactory().createSocket());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
}